package com.qianfeng.chinamibile.apigateway.filters;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qianfeng.chinamibile.apigateway.cache.GrayReleaseLocalCache;
import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Jackiechan on 2021/11/22/下午3:47
 *
 * @author Jackiechan
 * @version 1.0
 * 人学始知道，不学非自然。
 * @since 1.0
 */
@Component
public class GrayReleaseFIlter extends ZuulFilter {
    //key是serviceid+url value放的就是多少个标识 比如10个1 20个2等等
    private Map<String, List<String>> urlGrayConfig = new ConcurrentHashMap<>();

    private GrayReleaseLocalCache grayReleaseLocalCache;

    @Autowired
    public void setGrayReleaseLocalCache(GrayReleaseLocalCache grayReleaseLocalCache) {
        this.grayReleaseLocalCache = grayReleaseLocalCache;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 200;
    }

    @Override
    public boolean shouldFilter() {
        //判断当前请求的地址
        RequestContext currentContext = RequestContext.getCurrentContext();
        Object id = currentContext.get(FilterConstants.SERVICE_ID_KEY);
        Object uri = currentContext.get(FilterConstants.REQUEST_URI_KEY);
        System.err.println(id +"---->"+ uri);
        Map<String, List<Map>> grayReleaseMap = grayReleaseLocalCache.getGrayReleaseMap();//灰度的map
        List<Map> maps = grayReleaseMap.get(id.toString() + uri);
        System.err.println(maps);

        boolean isShould    = currentContext.sendZuulResponse() && maps != null && maps.size() > 0;
        if (isShould) {
            currentContext.put("grayrelease", maps);
            currentContext.put("grayreleasekey", id.toString() + uri);
        }
        return isShould;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        List<Map> grayreleaseMap = (List<Map>) currentContext.get("grayrelease");//保存的就是策略
        Object grayreleasekey = currentContext.get("grayreleasekey");
        //计算生成次数，并且洗牌保存到成员变量中
        //根据洗牌后的第0个位置获取一个标识出来，然后转发过来
        List<String> grayConfigList = urlGrayConfig.get(grayreleasekey.toString());
        if (grayConfigList == null) {
            grayConfigList = new ArrayList<>();
            urlGrayConfig.put(grayreleasekey.toString(), grayConfigList);
        }
        if ( grayConfigList.size() == 0) {
            List<String> finalGrayConfigList = grayConfigList;
            grayreleaseMap.forEach(item->{
                Integer percent = (Integer) item.get("percent");
                String forward = (String) item.get("forward");
                for (Integer integer = percent; integer > 0; integer--) {
                    finalGrayConfigList.add(forward);//添加指定格式的标识
                }
            });
            Collections.shuffle(grayConfigList);
        }
        String gray = grayConfigList.remove(0);//标识
        //设置标识，转发到对应的服务上
        RibbonFilterContextHolder.getCurrentContext().add("forward", gray);//这句话就代表将请求路由到metadata-map里forward为2的那个服务
        return null;
    }
}
